package com.ddzh.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ddzh.dto.SetmealDto;
import com.ddzh.entity.PageReq;
import com.ddzh.entity.PageRes;
import com.ddzh.mapper.SetmealMapper;
import com.ddzh.pojo.Setmeal;
import com.ddzh.pojo.SetmealGroup;
import com.ddzh.service.CheckGroupService;
import com.ddzh.service.CheckItemService;
import com.ddzh.service.SetmealService;
import com.ddzh.service.SetmealGroupService;
import com.ddzh.utils.RedisUtil;
import com.ddzh.utils.UploadUtils;
import com.ddzh.vo.CheckGroupVo;
import com.ddzh.vo.SetmealVo;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {

//    @Resource
//    private RedisTemplate<String,Object> redisTemplate;

    @Resource
    private SetmealGroupService setmealGroupService;

    @Resource
    private CheckGroupService checkGroupService;

    @Resource
    private CheckItemService checkItemService;

    @Override
    public PageRes<Setmeal> findByPage(PageReq pageReq) {
        PageRes<Setmeal> pageRes = new PageRes<>();

        IPage<Setmeal> iPage = new Page<>();
        iPage.setCurrent(pageReq.getCurrentPage());
        iPage.setSize(pageReq.getPageSize());

        QueryWrapper<Setmeal> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_delete",0);
        if(pageReq.getQueryString()!=null && "".equals(pageReq.getQueryString().trim())==false){
            queryWrapper.and(wrapper->{
                wrapper.like("name",pageReq.getQueryString()).or()
                        .like("code",pageReq.getQueryString()).or()
                        .like("helpcode",pageReq.getQueryString());
            });
        }
        queryWrapper.orderByDesc("id");

        IPage<Setmeal> page = this.page(iPage, queryWrapper);
        pageRes.setTotal(page.getTotal());
        pageRes.setList(page.getRecords());
        return pageRes;
    }

    @Transactional
    @Override
    public boolean saveOrUpdateDto(SetmealDto setMealDto) {
        if (setMealDto.getSetmeal().getId()==0){//添加检查组
            if (this.baseMapper.findByCode(setMealDto.getSetmeal().getCode())!=null){
                return false;
            }
            if (this.baseMapper.findByName(setMealDto.getSetmeal().getName())!=null){
                return false;
            }
        }

        //如果是更新的图片，需要将原图片删除1.直接在这里调用删除 2.将图片单独放在一个集合中统一删除
        //图片更新前的地址
        String originalImg=null;
        //判断有没有图片更新
        String img = setMealDto.getSetmeal().getImg();//前端上传新图片
        //如果id为null说明是新增数据
//            if(setMealDto.getSetmeal().getId()!=null){

        //根据 套餐id 查询 套餐
        Setmeal setmeal = this.queryById(setMealDto.getSetmeal().getId());
        //判断：是否更新了图片 - 只有套餐存在，上传图片存在时才更新了图片
        if (setmeal!=null && img!=null) {
            //获取
            originalImg = setmeal.getImg();
            //将一定会删除的照片存入redis的一个set集合中 键：edit
            RedisUtil.addToSet("edit", originalImg);
            //直接删除oss中原图片
//            boolean boo = UploadUtils.deleteFileName(originalImg);
//            System.out.println("删除oss中原图片是否成功 = " + boo);
        }
        //1.保存套餐信息
        this.saveOrUpdate(setMealDto.getSetmeal());
        System.out.println("setMealDto.getSetMeal().toString() = " + setMealDto.getSetmeal().toString());

        //将正确的img path移除出set集合
        RedisUtil.removeSetMember("file:allset",img);
        //2.保存检查组
        //清空套餐盒检查组的关系
        setmealGroupService.deleteBySetmealId(setMealDto.getSetmeal().getId());
        //批量保存
        List<SetmealGroup> list = new ArrayList<>();
        //遍历检查组id
        for (Long groupId : setMealDto.getGroupIds()) {
            SetmealGroup setmealGroup = new SetmealGroup();
            setmealGroup.setGroupId(groupId);
            setmealGroup.setSetmealId(setMealDto.getSetmeal().getId());
            list.add(setmealGroup);
        }
        setmealGroupService.saveOrUpdateBatch(list);
        return true;
    }

   @Override
    public Setmeal queryById(Long id) {
        QueryWrapper<Setmeal> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id",id);
        return this.getOne(queryWrapper);
    }

    @Override
    public List<Setmeal> findAll() {
        //查询所有
        return this.list();
    }

    @Override
    public boolean deleteById(Long setmeal_id) {
        Setmeal setMeal = new Setmeal();
        setMeal.setId(setmeal_id);
        setMeal.setIs_delete(1);
        return this.updateById(setMeal);
    }

    @Transactional
    @Override
    public boolean clearOssObject() {
        Set<Object> sets = RedisUtil.getMembersOfSet("file:allset");
        for (Object obj : sets) {
            String path = (String)obj;
            //对应的redis中键过期才请求oss对象
            if (RedisUtil.get("file:"+path)==null){
                //删除oss对象
                UploadUtils.deleteFileName(path);
                //清除redis缓存
                RedisUtil.removeSetMember("file:allset",path);
            }
        }
        //删除编辑修改后的原图片
        Set<Object> editImg = RedisUtil.getMembersOfSet("edit");
        //判断集合是否为null
        if (editImg!=null){
            //遍历集合
            for (Object obj : editImg) {
                String path = (String)obj;
                //删除集合中每一张图片
                RedisUtil.removeSetMember("edit",path);
            }
        }
        return true;
    }

    @Override
    public SetmealVo getDetail(Long id) {
        //返回的结果数据
        SetmealVo setmealVo =null;
        //0.先从redis中取数据
        Set<Object> set = RedisUtil.getMembersOfSet(id+"");//根据id只能查询出一个数据
        System.out.println("set = " + set);
        if (set.size()>0){
            for (Object obj : set) {
                System.out.println("走 缓存 查数据。。。。。。。。。。。");
                setmealVo = (SetmealVo) obj;
            }
        }else {//缓存中没有=》走数据库
            //1.查询并封装套餐信息,不用自带的函数getOne这样还要用set封装
            setmealVo = getInfo(id);
            //2.查询并封装检查组信息
            setmealVo.setCheckGroupVo(checkGroupService.getDetail(id));

//            //获取setmealId对应的检查组id，groupIds
//            List<Long> groupIds = getGroupIds(setmealVo);
//
//            //TODO:根据 groupIds查询并封装检查项信息
//            //3.遍历检查组，根据id查询并封装检查项信息
//            if (groupIds.size()>0){
//                for (Long groupId : groupIds) {
//
//                }
//                for (CheckGroupVo checkGroupVo : setmealVo.getCheckGroupVo()) {
//                    checkGroupVo.setCheckItemList(checkItemService.getDetail(checkGroupVo.getId()));
//                }
//            }

            //3.遍历检查组，根据id查询并封装检查项信息
            if (setmealVo.getCheckGroupVo()!=null){
                for (CheckGroupVo checkGroupVo : setmealVo.getCheckGroupVo()) {
                    checkGroupVo.setCheckItemList(checkItemService.getDetail(checkGroupVo.getId()));
                }
            }
            //将取到的数据放入redis中，下次从redis中取，如果redis中没有再从数据库取
//            redisTemplate.opsForSet().add(id+"",setmealVo);
            RedisUtil.addToSet(id+"",setmealVo);

            System.out.println("走 数据库 查数据。。。。。。。。。。。");
        }
        return setmealVo;
    }

    private List<Long> getGroupIds(SetmealVo setmealVo) {
        List<Long> groupIds = new ArrayList<>();

        //先从缓存中读取setmealId对应的groupIds==》减少数据库查询次数
//        Set<Object> groupIdSets = redisTemplate.opsForSet().members(setmealVo.getId() + "groupIds");
        Set<Object> groupIdSets = RedisUtil.getMembersOfSet(setmealVo.getId() + "groupIds");
        //存放检查组id
        //判null
        if (groupIdSets.size()>0){
            //缓存中有数据走缓存，遍历集合 groupIdSets 查询每一个检查组的检查项
            for (Object groupIdSet : groupIdSets) {
                groupIds.add((Long) groupIdSet);
            }
            System.out.println("从 缓存 中取出 groupIds 使用。。。。。。。。。。。");
        }else{
            //缓存中没有就从setmealVo中取出放入缓存
            //收集所有的groupId，并存入缓存中
            if (setmealVo.getCheckGroupVo()!=null){
                for (CheckGroupVo checkGroupVo : setmealVo.getCheckGroupVo()) {
                    groupIds.add(checkGroupVo.getId());
//                    checkGroupVo.setCheckItemList(checkItemService.getDetail(checkGroupVo.getId()));
                }
                //将setmealId对应的groupIds存入缓存中
//                redisTemplate.opsForSet().add(setmealVo.getId()+"groupIds",groupIds);
                RedisUtil.addToSet(setmealVo.getId()+"groupIds",groupIds);
                System.out.println("从setmealVo中取出 groupIds 使用，并放入缓存。。。。。。。。。。。");
            }
        }
        return groupIds;

    }

    @Override
    public SetmealVo getInfo(Long id) {
        return this.baseMapper.getInfo(id);
    }

    @Override
    public Setmeal findByItemId(Long itemId) {
        return this.baseMapper.findByItemId(itemId);
    }

    @Override
    public Setmeal findByGroupId(Long groupId) {
        return this.baseMapper.findByGroupId(groupId);
    }
}
